/**
 * Mock类组织规范指导
 * 
 * 基于10,892个测试文件的分析：
 * - 25%的测试文件使用Mock
 * - Mock头文件命名：mock_xxx.h (53%) > xxx_mock.h (22%)
 * - Mock成员定义：通常在.h文件的protected部分
 * - SetUp初始化：优先std::make_shared
 */

export class MockOrganizationGuidance {
    
    /**
     * 获取Mock组织的完整指导
     */
    public static getGuidance(): string {
        return `

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
## 🎭 Mock类组织规范（基于10,892个真实UT的分析）
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

### 📊 数据背景
- **25%的测试文件使用Mock**
- **Mock头文件命名规范**：\`mock_xxx.h\` (53%) > \`xxx_mock.h\` (22%)
- **Mock成员变量位置**：.h文件的protected部分（最常见）
- **初始化方式**：\`std::make_shared\` > \`new\` > \`sptr::MakeSptr\`

---

### 🏗️ Mock类组织的三种方式

#### 方式1：使用已有Mock头文件（最推荐，约10%的UT）

\`\`\`cpp
// xxx_test.h
#include "mock_ipc_skeleton.h"           // ✅ 已有Mock类
#include "mock_access_token_kit.h"       // ✅ 已有Mock类

class MyClassTest : public testing::Test {
protected:
    void SetUp() override;
    void TearDown() override;
    
    std::shared_ptr<MockIPCSkeleton> mockIPCSkeleton_ = nullptr;
    std::shared_ptr<MockAccessTokenKit> mockAccessTokenKit_ = nullptr;
    std::shared_ptr<MyClass> instance_ = nullptr;
};

// xxx_test.cpp
void MyClassTest::SetUp() {
    mockIPCSkeleton_ = std::make_shared<MockIPCSkeleton>();
    mockAccessTokenKit_ = std::make_shared<MockAccessTokenKit>();
    instance_ = std::make_shared<MyClass>(mockIPCSkeleton_, mockAccessTokenKit_);
}

HWTEST_F(MyClassTest, Test_001, TestSize.Level1) {
    EXPECT_CALL(*mockIPCSkeleton_, GetCallingTokenID())
        .WillOnce(Return(Security::AccessToken::AccessTokenID(0)));
    
    bool result = instance_->CheckPermission();
    EXPECT_TRUE(result);
}
\`\`\`

**何时使用**：
- ✅ 当Mock类已存在于test/mock/目录或相关头文件中
- ✅ 系统服务相关的Mock（IPC, AccessToken, AccountManager等）
- ✅ 多个测试共享的Mock类

**检查方法**：
\`\`\`cpp
// 在测试目录或上级目录的mock/或include/目录中搜索：
// - mock_ipc_skeleton.h
// - ipc_skeleton_mock.h
// - mock_*.h
\`\`\`

---

#### 方式2：在测试文件开头定义Mock类（最常见，约90%使用Mock的UT）

\`\`\`cpp
// xxx_test.cpp
#include "my_class.h"
#include <gtest/gtest.h>
#include <gmock/gmock.h>

using namespace testing;
using namespace testing::ext;

namespace OHOS {
namespace MyNamespace {

// ✅ 在namespace内，class定义前定义Mock类
class MockDependency : public IDependency {
public:
    MOCK_METHOD(int32_t, GetValue, (), (override));
    MOCK_METHOD(bool, Process, (const std::string&), (override));
    MOCK_METHOD(int32_t, FetchData, (std::vector<int>&), (override));
};

// 测试类定义
class MyClassTest : public testing::Test {
public:
    static void SetUpTestCase(void);
    static void TearDownTestCase(void);
    void SetUp();
    void TearDown();

protected:
    std::shared_ptr<MockDependency> mockDependency_ = nullptr;
    std::shared_ptr<MyClass> instance_ = nullptr;
};

void MyClassTest::SetUpTestCase(void) {}
void MyClassTest::TearDownTestCase(void) {}

void MyClassTest::SetUp() {
    mockDependency_ = std::make_shared<MockDependency>();
    instance_ = std::make_shared<MyClass>(mockDependency_);
}

void MyClassTest::TearDown() {
    mockDependency_ = nullptr;
    instance_ = nullptr;
}

HWTEST_F(MyClassTest, Test_001, TestSize.Level1) {
    EXPECT_CALL(*mockDependency_, GetValue())
        .WillOnce(Return(100));
    
    int result = instance_->Calculate();
    EXPECT_EQ(result, 100);
}

} // namespace MyNamespace
} // namespace OHOS
\`\`\`

**何时使用**：
- ✅ Mock类仅在当前测试文件使用
- ✅ 简单的Mock接口（2-5个方法）
- ✅ 不需要跨测试文件共享

**位置要求**：
- ✅ **必须在namespace内**
- ✅ **必须在测试类定义之前**
- ✅ **位于文件前20%**（约17.7%的平均位置）

---

#### 方式3：创建独立Mock头文件（复杂Mock或多测试共享）

**文件结构**：
\`\`\`
test/
├── unittest/
│   ├── src/
│   │   └── my_class_test.cpp
│   └── include/
│       └── my_class_test.h          // ✅ 包含Mock成员变量定义
└── mock/
    └── include/
        └── mock_dependency.h        // ✅ Mock类定义
\`\`\`

**mock_dependency.h**：
\`\`\`cpp
#ifndef MOCK_DEPENDENCY_H
#define MOCK_DEPENDENCY_H

#include "i_dependency.h"
#include <gmock/gmock.h>

namespace OHOS {
namespace MyNamespace {

class MockDependency : public IDependency {
public:
    MOCK_METHOD(int32_t, GetValue, (), (override));
    MOCK_METHOD(bool, Process, (const std::string&), (override));
    MOCK_METHOD(int32_t, FetchData, (std::vector<int>&), (override));
};

} // namespace MyNamespace
} // namespace OHOS

#endif // MOCK_DEPENDENCY_H
\`\`\`

**my_class_test.h**：
\`\`\`cpp
#ifndef MY_CLASS_TEST_H
#define MY_CLASS_TEST_H

#include <gtest/gtest.h>
#include <memory>
#include "mock_dependency.h"   // ✅ 引入Mock头文件

namespace OHOS {
namespace MyNamespace {

class MyClassTest : public testing::Test {
public:
    void SetUp() override;
    void TearDown() override;
    
protected:
    std::shared_ptr<MockDependency> mockDependency_ = nullptr;  // ✅ protected成员
    std::shared_ptr<MyClass> instance_ = nullptr;
};

} // namespace MyNamespace
} // namespace OHOS

#endif // MY_CLASS_TEST_H
\`\`\`

**my_class_test.cpp**：
\`\`\`cpp
#include "my_class_test.h"
#include "my_class.h"

using namespace testing;
using namespace testing::ext;

namespace OHOS {
namespace MyNamespace {

void MyClassTest::SetUp() {
    mockDependency_ = std::make_shared<MockDependency>();
    instance_ = std::make_shared<MyClass>(mockDependency_);
}

void MyClassTest::TearDown() {
    mockDependency_ = nullptr;
    instance_ = nullptr;
}

HWTEST_F(MyClassTest, Test_001, TestSize.Level1) {
    EXPECT_CALL(*mockDependency_, GetValue())
        .WillOnce(Return(100));
    
    int result = instance_->Calculate();
    EXPECT_EQ(result, 100);
}

} // namespace MyNamespace
} // namespace OHOS
\`\`\`

**何时使用**：
- ✅ Mock类被多个测试文件使用
- ✅ Mock类很复杂（>10个方法）
- ✅ Mock类需要在多个模块间共享

---

### 🎯 决策流程图

\`\`\`
检测到需要Mock？
    ↓
    ├─ 已有mock_xxx.h？ ─→ 是 ─→ 【方式1】使用已有Mock头文件
    │                                - #include "mock_xxx.h"
    │                                - protected成员变量
    │                                - SetUp中初始化
    ↓
    └─ 否 ─→ Mock类复杂度？
              ↓
              ├─ 简单（<5个方法）且仅本文件用 ─→ 【方式2】在test.cpp开头定义
              │                                      - namespace内，class前
              │                                      - 文件前20%
              │                                      - 无需额外头文件
              ↓
              └─ 复杂或多文件共享 ─→ 【方式3】创建独立Mock头文件
                                      - test/mock/include/mock_xxx.h
                                      - test.h中protected成员
                                      - test.cpp中#include
\`\`\`

---

### 📋 Mock成员变量命名规范

\`\`\`cpp
// ✅ 推荐：描述性名称 + 下划线后缀
std::shared_ptr<MockIPCSkeleton> mockIPCSkeleton_ = nullptr;
std::shared_ptr<MockAccessTokenKit> mockAccessTokenKit_ = nullptr;
std::shared_ptr<MockSystemAbilityManager> mockSaManager_ = nullptr;

// ❌ 避免：过于简短或不清晰
std::shared_ptr<MockIPCSkeleton> mock1_ = nullptr;  // 不清晰
std::shared_ptr<MockIPCSkeleton> m_ = nullptr;      // 太短
\`\`\`

---

### 🔧 SetUp/TearDown最佳实践

\`\`\`cpp
void MyClassTest::SetUp() {
    // 1. 初始化Mock对象（优先std::make_shared）
    mockDependency_ = std::make_shared<MockDependency>();
    mockSaManager_ = std::make_shared<MockSystemAbilityManager>();
    
    // 2. 配置全局Mock行为（如果有）
    EXPECT_CALL(*mockDependency_, GetCommonMethod())
        .WillRepeatedly(Return(ERR_OK));
    
    // 3. 初始化被测对象
    instance_ = std::make_shared<MyClass>(mockDependency_, mockSaManager_);
}

void MyClassTest::TearDown() {
    // ✅ 释放Mock对象
    mockDependency_ = nullptr;
    mockSaManager_ = nullptr;
    
    // ✅ 释放被测对象
    instance_ = nullptr;
}
\`\`\`

---

### 🚨 常见错误和解决方案

#### 错误1：Mock类未定义

\`\`\`cpp
// ❌ 错误：EXPECT_CALL使用了未定义的Mock类
EXPECT_CALL(*mockIPCSkeleton_, GetCallingTokenID())  // MockIPCSkeleton未定义
    .WillOnce(Return(0));
\`\`\`

**解决方案**：
\`\`\`cpp
// ✅ 方案1：检查是否有已有Mock头文件
#include "mock_ipc_skeleton.h"

// ✅ 方案2：在文件开头定义Mock类
class MockIPCSkeleton : public IPCSkeleton {
public:
    MOCK_METHOD(uint32_t, GetCallingTokenID, (), (override));
};
\`\`\`

---

#### 错误2：Mock成员变量未声明

\`\`\`cpp
// ❌ 错误：测试函数中使用了未声明的成员
HWTEST_F(MyTest, Test_001, TestSize.Level1) {
    EXPECT_CALL(*mockDependency_, Method())  // mockDependency_未声明
        .WillOnce(Return(0));
}
\`\`\`

**解决方案**：
\`\`\`cpp
// ✅ 在类定义的protected部分声明
class MyTest : public testing::Test {
protected:
    void SetUp() override;
    void TearDown() override;
    
    std::shared_ptr<MockDependency> mockDependency_ = nullptr;  // ✅ 声明
    std::shared_ptr<MyClass> instance_ = nullptr;
};
\`\`\`

---

#### 错误3：Mock头文件未包含

\`\`\`cpp
// ❌ 错误：编译错误 - MockDependency not found
class MockDependency : public IDependency {  // IDependency未定义
    // ...
};
\`\`\`

**解决方案**：
\`\`\`cpp
// ✅ 包含必要的头文件
#include "i_dependency.h"    // ✅ 被Mock的接口
#include <gmock/gmock.h>     // ✅ gmock头文件
#include <gtest/gtest.h>     // ✅ gtest头文件

using namespace testing;     // ✅ using声明

class MockDependency : public IDependency {
    MOCK_METHOD(...);
};
\`\`\`

---

### 💡 生成一致性保证

**问题**：同一函数多次生成，结果不一致

**原因**：
1. LLM的温度参数导致随机性
2. 上下文信息不完整
3. 没有明确的决策规则

**解决方案**：

\`\`\`markdown
## 必须遵守的Mock组织规则

1. **优先检查已有Mock**：
   - 搜索test/mock/目录
   - 搜索mock_*.h文件
   - 如果存在，必须使用已有Mock

2. **Mock类定义位置（按优先级）**：
   - 第1优先：使用已有Mock头文件
   - 第2优先：在test.cpp的namespace内、测试类前定义（简单Mock）
   - 第3优先：创建新的mock_xxx.h文件（复杂Mock）

3. **Mock成员变量位置**：
   - 始终在测试类的protected部分
   - 使用std::shared_ptr<MockXxx>类型
   - 命名格式：mockXxx_

4. **SetUp初始化**：
   - 始终使用std::make_shared初始化Mock
   - 先初始化Mock，再初始化被测对象
   - 在TearDown中置nullptr

遵循以上规则可保证每次生成结果一致！
\`\`\`

---

### 📊 真实项目统计（10,892个测试文件）

| 模式 | 数量 | 比例 |
|------|------|------|
| **使用Mock的测试** | 2,720 | 25% |
| **不使用Mock的测试** | 8,172 | 75% |
| **mock_xxx.h命名** | 2,768 | 53% |
| **xxx_mock.h命名** | 1,148 | 22% |
| **std::make_shared初始化** | 34 | 优先 |
| **protected成员变量** | 21 | 主流 |

**结论**：
- ✅ 75%的UT不需要Mock，不要过度使用
- ✅ 使用Mock时，优先\`mock_xxx.h\`命名
- ✅ Mock成员定义在protected部分
- ✅ 使用std::make_shared初始化

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
`;
    }
}

